package org.yang.common.utils.jwt;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.yang.common.core.constant.SystemConstant;
import org.yang.common.core.exception.BaseException;
import org.yang.common.core.model.UserInfo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.stream.Collectors;

/**
 * JWT令牌解析用户信息工具
 * @author lslands
 * @version 1.0
 * @date 2023/3/15 11:10
 * @description:
 */
@Slf4j
public class JwtTokenAnalysisUtli {
    public static final String PUBLIC_KEY = "publicKey.key";


    /**
     * 解析JWT令牌
     * @return Map
     * @author lslands
     * @date 2024/5/11 15:19
     */

    static Map analysisJwt(){
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = null;
            if (attributes != null) {
                request = attributes.getRequest();
            }
            String token = null;
            if (request != null) {
                token = request.getHeader("Authorization").replace("Bearer ","");
            }
            Jwt jwt = null;
            if (token != null) {
                jwt = JwtHelper.decodeAndVerify(token, new RsaVerifier(getPublicKey()));
            }
            if (jwt != null) {
                return JSON.parseObject(jwt.getClaims(), Map.class);
            }
            return null;
        }catch (BaseException e){
            log.error("查询用户信息异常:{}",e.getMessage());
            return null;
        }
    }

    /**
     * 解析令牌获取登录信息
     * @return AccountInfo
     */
    public static UserInfo useMe(){
        String strObj = JSONObject.toJSONString(analysisJwt(), true);
        return JSONObject.parseObject(strObj, UserInfo.class);
    }

    /**
     * 解析令牌获取登录用户名
     * @return String
     */
    public static String useName(){
        Map map = analysisJwt();
        assert map != null;
        return (String) map.get("username");
    }

    /**
     * 解析令牌获取登录用户id
     * @return Long
     */
    public static Long useId() {
        Map map = analysisJwt();
        assert map != null;
        return Long.parseLong(map.get("userId").toString());
    }


    /**
     * 解析登录用户企业Id
     * @return String
     */
    public static Long companyId(){
        Map map = analysisJwt();
        assert map != null;
        return Long.parseLong(map.get("companyId").toString());
    }

    /**
     * 解析登录用户角色集
     * @return 角色编码集
     */
    public static List<String> roles(){
        Map map = analysisJwt();
        assert map != null;
        String roles = map.get("roles").toString();
        JSONArray jsonArray = JSON.parseArray(roles);
        return jsonArray.toJavaList(String.class);
    }

    /**
     * 获取非对称加密公钥
     * @return String
     */
    private static String getPublicKey() throws BaseException{
        Resource resource = new ClassPathResource(PUBLIC_KEY);
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream());
            BufferedReader br = new BufferedReader(inputStreamReader);
            return br.lines().collect(Collectors.joining("\n"));
        }catch (IOException e){
            throw new BaseException("公钥获取失败");
        }
    }

    /**
     * 判断角色是否为指定放行角色
     * @return 布尔
     * @throws BaseException 角色获取异常
     */
    public static Boolean isRoot() throws BaseException{
        List<String> roles = JwtTokenAnalysisUtli.roles();
        return new HashSet<>(roles).containsAll(SystemConstant.SUPER_ROLE);
    }

    /**
     * 判断是否为超级企业
     * @return 布尔
     * @throws BaseException 角色获取异常
     */
    public static Boolean isCompany() throws BaseException{
        Long companyId = JwtTokenAnalysisUtli.companyId();
        return companyId.equals(SystemConstant.SUPER_COMPANY);
    }
}
